﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using TpOffice.Forms;
using TpOffice.Interfaces;
using TpOffice.Properties;
using TpBaseObjects.Models;
using TpBaseObjects.Objects;
using TpContracts;
using TpData.Manager;
using TpExtensions;
using TpTools;
using myOffice = Microsoft.Office.Interop;
using Microsoft.Office.Interop.Excel;
using TpBaseObjects.Interfaces;

namespace TpOffice.Controller {

    public class CashSaleDetailController : IController {

        #region Members

        private CashSaleDetailForm myForm;
        private const string errType = "Err";
        private const string logType = "Log";
        private const string logArea = "TpOffice.Controller.CashSaleDetailController";
        private string orgName = "";

        #endregion

        #region Constructor

        public CashSaleDetailController(ITecForm form) {
            this.myForm = form as CashSaleDetailForm;
        }

        #endregion

        #region Methods

        public void AfterDeleteDetailsRow(object sender, DataGridViewRowEventArgs e) {
            SetSummenValues();
        }

        public void BeforeDeletingDetailsRow(object sender, DataGridViewRowCancelEventArgs e) {
            string msg = "Wollen Sie diese Zeile wirklich löschen?";
            DialogResult res = MessageBox.Show(msg, "Barverkauf", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
            if (res == DialogResult.No) {
                e.Cancel = true;
            }
            if (!e.Cancel) {
                //CashSaleDetailsModel dm = e.Row.DataBoundItem as CashSaleDetailsModel;
                //this.myForm.MyModel.MyDetails.Remove(dm);
                this.myForm.MyModel.IsDirty = true;
            }
        }

        private void ChangedDetailProperty(object sender, PropertyChangedEventArgs e) {
            if (e.PropertyName == "ProductID") {
                CashSaleDetailsModel mod = sender as CashSaleDetailsModel;
                CashSaleProductsModel pm = GetMyProduct(mod.ProductID);
                TaxesModel tm = GetMyTax(pm.TaxCode);
                if (pm != null) {
                    mod.ProductName = pm.ProductName;
                    mod.Price = pm.SalesPrice;
                    mod.Unity = pm.Unity;
                    mod.TaxCode = pm.TaxCode;
                    mod.TaxRate = tm.TaxRate;
                }
            }
            ChangedMyProperty(sender, e, true);
        }

        private void ChangedMyJobProperty(object sender, PropertyChangedEventArgs e) {
            ChangedMyProperty(sender, e, true);
        }

        private void ChangedMyProperty(object sender, PropertyChangedEventArgs e) {
            ChangedMyProperty(sender, e, false);
        }

        private void ChangedMyProperty(object sender, PropertyChangedEventArgs e, bool details) {
            if (details) {
                SetSummenValues();
                this.myForm.MyModel.IsDirty = true;
            }
            if (e.PropertyName == "PaymentMode") {
                SetChargeForward();
                SetJobs();
                this.myForm.MyPaymentMode = this.myForm.MyModel.PaymentMode;
                this.myForm.MyModel.IsDirty = true;
                this.SetSummenValues();
            }
            if (e.PropertyName == "OrgKey") {
                foreach (OrganisationsShortListObj org in this.myForm.MyOrganisationModel) {
                    if (org.OrgKey == this.myForm.MyModel.OrgKey) {
                        this.myForm.MyModel.OrgName = org.OrgName;
                        this.myForm.MyModel.OrgFullName = org.OrgData;
                        orgName = org.Prefix.AddSpace() + org.OrgName;
                    }
                }
                if (this.myForm.MyModel.MyJobDetails != null) {
                    foreach (JobObj job in this.myForm.MyModel.MyJobDetails) {
                        job.Area = orgName;
                        job.SubArea = "Bv" + DateTime.Now.Date.Year.ToString().Right(2);
                    }
                }
                this.myForm.MyModel.IsDirty = true;
            }
            if (e.PropertyName == "OrderDate" || e.PropertyName == "SaleDate" || e.PropertyName == "OrderDetail") {
                this.myForm.MyModel.IsDirty = true;
            }
            if (e.PropertyName == "UseDeliveryAddress") {
                this.myForm.SetUseDeliveryAddess(this.myForm.MyModel.UseDeliveryAddress);
                this.myForm.MyModel.IsDirty = true;
            }
        }

        private bool CheckModelIsReadyForInvoice(CashSaleModel model, out List<string> error) {
            bool ret = true;
            List<string> tRet = new List<string>();

            if (model.OrgKey == 0) {
                tRet.Add("Es wurde kein Kunde ausgewählt!");
                ret = false;
            }
            error = tRet;
            if (model.MyDetails.Count == 0) {
                tRet.Add("Es wurden keine Details erfasst!");
                ret = false;
            }
            if (model.GrossPrice <= 0) {
                tRet.Add("VP kann nicht 0 sein!");
                ret = false;
            }
            return ret;
        }

        public void CreateInvoice(object sender, EventArgs e, CashSaleModel model) {
            if (model.NoInvoice) {
                List<string> errors;
                DialogResult res = MessageBox.Show("Wollen Sie jetzt eine Rechnung erstellen?", "Barverkauf", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (res == DialogResult.Yes) {
                    try {
                        if (!CheckModelIsReadyForInvoice(model, out errors)) {
                            string msg = "Es sind Fehleraufgetreten: " + Environment.NewLine;
                            foreach (string t1 in errors) {
                                msg += t1 + Environment.NewLine;
                            }
                            MessageBox.Show(msg, "Tec-Office", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            return;
                        }
                        bool wordStarted = Office.WordIsStarted();
                        string vorlage = Settings.Default.InvoiceTemplate;
                        if (model.PaymentMode == 3) {
                            vorlage = Settings.Default.InvoiceNachnahmeTemplate;
                        }
                        myOffice.Word.Application appWord = null;
                        model.InvoiceNo = CashSaleDataManager.GetCashSaleInvoiceNumber(model.CashSaleID, Contracts.MyUser.UserID);
                        string fileName = model.SaleDate.Year.ToString().Right(2) + model.InvoiceNo.ToString("000") + TpExtensions.Extensions.DocExt.DocX.GetStringValue();
                        string filePath = Settings.Default.RewePath + String.Format(Settings.Default.ReweCashSaleInvoicePath, model.SaleDate.Year.ToString().Right(2));
                        fileName = Path.Combine(filePath, fileName);
                        appWord = Office.GetWordApplication();
                        if (appWord != null) {
                            myOffice.Word.Document myDoc = Office.GetWordDocument(appWord, fileName, vorlage);
                            if (myDoc != null) {
                                Office.FillWordDocumentFields(appWord, myDoc, model);
                                myDoc.SaveAs2(FileName: fileName);
                                CashSaleDataManager.SaveCashSale(model);

                                Office.WriteInvoiceToBv(model);
                                if (model.WriteInvoiceToBvDate.Year > DateTime.Now.AddYears(-1).Year) {
                                    this.Save(model);
                                }

                                if (model.IsReadyForLiqui) {
                                    Office.WriteInvoiceToLiqui(model);
                                    if (model.WriteToLiquiDate.Year > DateTime.Now.AddYears(-1).Year) {
                                        this.Save(model);
                                    }
                                }


                                if (model.IsReadyForVrsp) {
                                    Office.WriteInvoiceToVrsp(model);
                                    if (model.WriteInvoiceToVrspDate.Year > DateTime.Now.AddYears(-1).Year) {
                                        this.Save(model);
                                    }
                                }

                                appWord.Visible = true;
                                appWord.Activate();
                            }
                        }
                    } catch (Exception ex) {
                        model.InvoiceNo = 0;
                        LogDataManager.SaveLog(Contracts.MyUser.UserID, errType, logArea, ex.Message, true);
                        MessageBox.Show("Fehler beim Anlegen der Rechnung: " + ex.Message, "Barverkauf", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    }
                }
            }
        }

        public void Dispose() {
        }

        public void LoadModels(int cashSaleID) {
            if (cashSaleID > 0) {
                this.myForm.MyModel = CashSaleDataManager.LoadCashSale(cashSaleID);
                if (this.myForm.MyModel != null) {
                    if (this.myForm.MyModel.MyDetails != null) {
                        this.myForm.MyDetailsModel = this.myForm.MyModel.MyDetails;
                    } else {
                        CashSaleDetailsModel cdm = new CashSaleDetailsModel();
                        cdm.PropertyChanged += new PropertyChangedEventHandler(ChangedDetailProperty);
                        this.myForm.MyDetailsModel.Add(cdm);
                    }
                    this.myForm.MyJobsModel = this.myForm.MyModel.MyJobDetails;
                }
            } else {
                CashSaleModel csm = new CashSaleModel(Contracts.MyUser.UserID);

                JobObj firstJob = GetJobAnforderungen();
                JobObj secondJob = GetJobAbrechnung();

                csm.MyJobDetails.Add(firstJob);
                csm.MyJobDetails.Add(secondJob);

                this.myForm.MyModel = csm;
            }
            this.myForm.MyModel.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(ChangedMyProperty);
            if (this.myForm.MyDetailsModel != null) {
                foreach (CashSaleDetailsModel dm in this.myForm.MyDetailsModel) {
                    dm.PropertyChanged += new PropertyChangedEventHandler(ChangedDetailProperty);
                }
            }
            if (this.myForm.MyJobsModel != null) {
                foreach (JobObj job in this.myForm.MyJobsModel) {
                    job.PropertyChanged += new PropertyChangedEventHandler(ChangedMyJobProperty);
                }
            }

            this.myForm.MyTaxesModel = TpAccountingDataManager.LoadTaxes();
            this.myForm.MyProductsModel = TpAccountingDataManager.LoadProducts();
            this.myForm.MyPaymentModesModel = CashSaleDataManager.LoadPaymentModes();
            this.myForm.MyOrganisationModel = CommonDataManager.LoadOrganisationsShortList();
            this.myForm.MyUserModel = TecUserDataManager.LoadTecUser();
        }

        public void Save(IBaseObject myObject) {
            CashSaleModel myModel = myObject as CashSaleModel;
            if (myModel.InvoiceNo == -1) {
                myModel.InvoiceNo = 0;
            }
            if (!CashSaleDataManager.SaveCashSale(myModel)) {
                MessageBox.Show("Error während Speichern des Datensatzes!", "Bar-Verkauf", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } else {
                myModel.IsDirty = false;
            }
        }

        private void SetChargeForward() {
            CashSaleProductsModel pmPackage = GetChargeForward(34);
            CashSaleProductsModel pmChargeForward = GetChargeForward(35);
            CashSaleDetailsModel mod = new CashSaleDetailsModel();
            CashSaleDetailsModel mod2 = new CashSaleDetailsModel();

            #region Insert

            if (this.myForm.MyPaymentMode != this.myForm.MyModel.PaymentMode && this.myForm.MyModel.PaymentMode == 3) {

                TaxesModel tm = GetMyTax(pmPackage.TaxCode);
                if (pmPackage != null) {
                    mod.ProductID = pmPackage.ProductID;
                    mod.ProductName = pmPackage.ProductName;
                    mod.Price = pmPackage.SalesPrice;
                    mod.Unity = pmPackage.Unity;
                    mod.Quantity = 1.0;
                    mod.TaxCode = pmPackage.TaxCode;
                    mod.TaxRate = tm.TaxRate;
                    mod.PropertyChanged += new PropertyChangedEventHandler(ChangedDetailProperty);
                    this.myForm.AddDetailsModel(mod);
                }
                if (pmChargeForward != null) {
                    tm = GetMyTax(pmChargeForward.TaxCode);
                    mod2.ProductID = pmChargeForward.ProductID;
                    mod2.ProductName = pmChargeForward.ProductName;
                    mod2.Price = pmChargeForward.SalesPrice;
                    mod2.Unity = pmChargeForward.Unity;
                    mod2.Quantity = 1.0;
                    mod2.TaxCode = pmChargeForward.TaxCode;
                    mod2.TaxRate = tm.TaxRate;
                    mod2.PropertyChanged += new PropertyChangedEventHandler(ChangedDetailProperty);
                    this.myForm.AddDetailsModel(mod2);
                }
            }

            #endregion

            #region Delete

            if (this.myForm.MyPaymentMode != this.myForm.MyModel.PaymentMode && this.myForm.MyPaymentMode == 3) {
                List<CashSaleDetailsModel> myList = new List<CashSaleDetailsModel>();
                foreach (CashSaleDetailsModel dm1 in (List<CashSaleDetailsModel>)this.myForm.bsMyDetails.DataSource) {
                    myList.Add(dm1);
                }
                foreach (CashSaleDetailsModel dm in myList) {
                    if (dm.ProductID == 34 || dm.ProductID == 35) {
                        this.myForm.bsMyDetails.Remove(dm);
                    }
                }
            }

            #endregion

        }

        private void SetJobs() {
            //JobObj jobAnf = GetJobAnforderungen();
            //JobObj jobAbr = GetJobAbrechnung();
            JobObj jobVpg = GetJobVerpackung();
            JobObj jobNn = GetJobNachnahme();

            #region Insert

            if (this.myForm.MyPaymentMode != this.myForm.MyModel.PaymentMode && this.myForm.MyModel.PaymentMode == 3) {
                jobVpg.ForChargeForward = true;
                jobVpg.Area = this.orgName;
                jobVpg.SubArea = "Bv" + DateTime.Now.Date.Year.ToString().Right(2);
                this.myForm.bsJobs.Add(jobVpg);
                jobNn.ForChargeForward = true;
                jobNn.Area = this.orgName;
                jobNn.SubArea = "Bv" + DateTime.Now.Date.Year.ToString().Right(2);
                this.myForm.bsJobs.Add(jobNn);
            }

            #endregion

            #region Delete

            if (this.myForm.MyPaymentMode != this.myForm.MyModel.PaymentMode && this.myForm.MyPaymentMode == 3) {
                List<JobObj> myList = new List<JobObj>();
                foreach (JobObj job in (List<JobObj>)this.myForm.bsJobs.DataSource) {
                    myList.Add(job);
                }
                foreach (JobObj job in myList) {
                    if (job.ForChargeForward) {
                        this.myForm.bsJobs.Remove(job);
                    }
                }
            }

            #endregion

        }

        public void ShowMyForm() {
            this.myForm.ShowDialog();
        }

        #endregion

        #region Events

        private void DataError(object sender, DataGridViewDataErrorEventArgs e) {
            //MessageBox.Show("Error");
        }

        public void AddingNewDetails(object sender, AddingNewEventArgs e) {
            CashSaleDetailsModel cdm = new CashSaleDetailsModel();
            cdm.PropertyChanged += new PropertyChangedEventHandler(ChangedDetailProperty);
            this.myForm.bsMyDetails.Add(cdm);
        }

        public void AddingNewJobs(object sender, AddingNewEventArgs e) {
            JobObj job = new JobObj();
            job.PropertyChanged += new PropertyChangedEventHandler(ChangedMyJobProperty);
            this.myForm.bsJobs.Add(job);
        }

        public void OrganisationsKeyUp(object sender, KeyEventArgs e) {
            if (e.KeyCode == Keys.F5 && !e.Shift && !e.Alt) {
                this.myForm.MyOrganisationModel = CommonDataManager.LoadOrganisationsShortList(true);
            }
        }

        public void SetSummenValues() {
            double sumNetto = 0.0;
            double sumUst = 0.0;

            if (this.myForm.MyModel.MyDetails != null) {
                foreach (CashSaleDetailsModel dm in this.myForm.MyModel.MyDetails) {
                    if (dm != null) {
                        sumNetto += dm.SalePrice;
                        sumUst += (dm.SalePrice * dm.TaxRate);
                    }
                }
            }
            if (this.myForm.MyModel != null) {
                this.myForm.MyModel.SalePrice = sumNetto;
                this.myForm.MyModel.Taxes = sumUst;
                this.myForm.MyModel.GrossPrice = sumNetto + sumUst;
                //this.bsCashSale.DataSource = this.MyModel;
            }
        }

        #endregion

        #region Functions

        private CashSaleProductsModel GetMyProduct(int productID) {
            CashSaleProductsModel myRet = new CashSaleProductsModel();
            foreach (CashSaleProductsModel pm in this.myForm.MyProductsModel) {
                if (pm.ProductID == productID) {
                    return pm;
                }
            }
            return myRet;
        }

        public void BeforeCloseMyForm(object sender, FormClosingEventArgs e) {
            if (this.myForm.MyModel.IsDirty) {
                DialogResult res = MessageBox.Show("Datensatz wurde noch nicht gespeichert. Wollen Sie jetzt speichern?", "Barverkauf", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation);
                if (res == DialogResult.Yes) {
                    this.Save(this.myForm.MyModel);
                    return;
                }
                if (res == DialogResult.No) {
                    return;
                }
            } else {
                return;
            }
            return;
        }

        private TaxesModel GetMyTax(int taxCode) {
            TaxesModel myRet = new TaxesModel();
            foreach (TaxesModel tm in this.myForm.MyTaxesModel) {
                if (tm.TaxCodeID == taxCode) {
                    return tm;
                }
            }
            return myRet;
        }

        private JobObj GetJobAbrechnung() {
            JobObj job = new JobObj();
            job.Datum = DateTime.Now.Date;
            job.Einheit = "Pa";
            job.Fahrzeug = "Lf";
            job.JobID = Guid.NewGuid();
            job.JobType = 2;
            job.Leistung = "Bv Abrechnung Kunde";
            job.LeistungProzent = 100.0;
            job.LeistungZeit = 0.25;
            job.Status = 1;
            job.Title = job.Leistung;
            job.UserID = Contracts.MyUser.UserID;
            job.SubArea = "Bv" + DateTime.Now.Date.Year.ToString().Right(2);
            return job;
        }

        private JobObj GetJobAnforderungen() {
            JobObj job = new JobObj();
            job.Datum = DateTime.Now.Date;
            job.Einheit = "Pa";
            job.Fahrzeug = "Lf";
            job.JobID = Guid.NewGuid();
            job.JobType = 1;
            job.Leistung = "Bv Klärung Anforderungen";
            job.LeistungProzent = 100.0;
            job.LeistungZeit = 0.25;
            job.Status = 1;
            job.Title = job.Leistung;
            job.UserID = Contracts.MyUser.UserID;
            job.SubArea = "Bv" + DateTime.Now.Date.Year.ToString().Right(2);
            return job;
        }

        private JobObj GetJobNachnahme() {
            JobObj job = new JobObj();
            job.Datum = DateTime.Now.Date;
            job.Einheit = "Pa";
            job.Fahrzeug = "Lf";
            job.JobID = Guid.NewGuid();
            job.JobType = 4;
            job.Leistung = "Bv Nachnahmegebühr";
            job.LeistungProzent = 100.0;
            job.LeistungZeit = 0.13;
            job.Status = 1;
            job.Title = job.Leistung;
            job.UserID = Contracts.MyUser.UserID;
            job.SubArea = "Bv" + DateTime.Now.Date.Year.ToString().Right(2);
            return job;
        }

        private JobObj GetJobVerpackung() {
            JobObj job = new JobObj();
            job.Datum = DateTime.Now.Date;
            job.Einheit = "Pa";
            job.Fahrzeug = "Lf";
            job.JobID = Guid.NewGuid();
            job.JobType = 3;
            job.Leistung = "Bv Verpackung, Postversand";
            job.LeistungProzent = 100.0;
            job.LeistungZeit = 0.13;
            job.Status = 1;
            job.Title = job.Leistung;
            job.UserID = Contracts.MyUser.UserID;
            job.SubArea = "Bv" + DateTime.Now.Date.Year.ToString().Right(2);
            return job;
        }

        private CashSaleProductsModel GetChargeForward(int producttID) {
            CashSaleProductsModel pm = CashSaleDataManager.LoadProduct(producttID);
            return pm;
        }


        #endregion

    }
}
